package psn.qiuyiping.autocad.dxffile;

import java.io.*;

import static java.nio.charset.StandardCharsets.UTF_8;

import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;

import static java.nio.charset.StandardCharsets.*;

public class DxfReader implements Closeable, Iterable<DxfData<String>> {
    final BufferedReader br;

    public DxfReader(InputStream sn) {
        br = new BufferedReader(new InputStreamReader(sn, UTF_8));
    }

    public DxfReader(String path) throws FileNotFoundException {
        this(new FileInputStream(path));
    }

    public static InputStream dwg2dxf(String dwgpath) {
        String path = "d:/eclipse/tfc/TeighaFileConverter.exe";

        try {
            File ss = new File(dwgpath);
            File dir = ss.getParentFile();
            int i = 0;
            File dirs, dird;
            while (true) {
                dirs = new File(dir, "temp_" + i + "_s");
                if (!dirs.exists() && dirs.mkdirs()) {
                    break;
                }
                i++;
            }
            copyFile(ss, new File(dirs, ss.getName()));
            dird = new File(dir, "temp_" + i + "_d");
            if (!dird.exists() && !dird.mkdirs()) {
                return null;
            }
            File out = new File(dwgpath.substring(0, dwgpath.length() - 4)
                    + ".dxf");
            if (out.exists()) {
                out.delete();
            }
            String cmd = path + " " + dirs.getAbsolutePath() + " "
                    + dird.getAbsolutePath() + " ACAD2013 DXF 0 1";
            System.out.println(cmd);
            Process process = Runtime.getRuntime().exec(cmd);
            process.waitFor();
            for (File file : dirs.listFiles()) {
                file.delete();
            }
            dirs.delete();
            if (out.exists()) {
                return new FileInputStream(out);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static long copyFile(File f1, File f2) throws Exception {
        long time = new Date().getTime();
        int length = 2097152;
        try (FileInputStream in = new FileInputStream(f1)) {
            try (FileOutputStream out = new FileOutputStream(f2)) {
                FileChannel inC = in.getChannel();
                FileChannel outC = out.getChannel();
                ByteBuffer b = ByteBuffer.allocateDirect(length);
                while (inC.read(b) != -1) {
                    inC.read(b);
                    b.flip();
                    outC.write(b);
                    b.clear();
                }
                inC.close();
                outC.close();
                return new Date().getTime() - time;
            }
        }
    }

    private static File createDir(String dirName) {
        String sysTemp = System.getProperty("java.io.tmpdir");
        File dir = new File(sysTemp + File.separator + dirName + File.separator
                + new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        if (dir.mkdirs()) {
            return dir;
        } else {
            return null;
        }
    }

    @Override
    public void close() throws IOException {
        br.close();
    }

    @Override
    public Iterator<DxfData<String>> iterator() {
        try {
            return new _Iterator();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    class _Iterator implements Iterator<DxfData<String>> {
        String line;
        int    code;

        public _Iterator() throws IOException {
            readCode();
        }

        @Override
        public boolean hasNext() {
            return line != null;
        }

        public void readCode() {
            try {
                line = br.readLine();
                if (line != null) {
                    code = Integer.parseInt(line.trim());
                }
            } catch (IOException e) {
                line = null;
                e.printStackTrace();
            }
        }

        @Override
        public DxfData<String> next() {
            try {
                line = null;
                String val = br.readLine();
                DxfData<String> data = new DxfData<>(code, val);
                if (is3D(code)) {
                    val = val.trim();
                    readCode();
                    val += "\t" + br.readLine().trim();
                    readCode();
                    if (code == data.code + 20) {
                        val += "\t" + br.readLine().trim();
                        readCode();
                    }
                    data.setVal(val);
                } else {
                    readCode();
                }
                return data;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;
        }

        boolean is3D(int code) {
            return code >= 10 && code <= 19 ||
                    code >= 110 && code <= 119 ||
                    code >= 210 && code <= 219 ||
                    code >= 1010 && code <= 1019;
        }
    }
}
